package com.hqbzl.c1.rlock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class TestFiveEat2 {
    public static void main(String[] args) {
        final Chopstick c1 = new Chopstick("筷子1");
        final Chopstick c2 = new Chopstick("筷子2");
        final Chopstick c3 = new Chopstick("筷子3");
        final Chopstick c4 = new Chopstick("筷子4");
        final Chopstick c5 = new Chopstick("筷子5");

        final Philosopher t1 = new Philosopher("苏格拉底", c1, c2);
        final Philosopher t2 = new Philosopher("柏拉图", c2, c3);
        final Philosopher t3 = new Philosopher("亚里士多德", c3, c4);
        final Philosopher t4 = new Philosopher("赫拉克利特", c4, c5);
        final Philosopher t5 = new Philosopher("阿基米德", c5, c1);
        //按同样的顺序释放，按同样的顺序获取，避免死锁
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }

    static class Chopstick extends ReentrantLock {
        private String name;

        public Chopstick(String name) {
            this.name = name;
        }
    }

    static class Philosopher extends Thread {
        private String name;
        private Chopstick left;
        private Chopstick right;

        public Philosopher(String name, Chopstick left, Chopstick right) {
            this.name = name;
            this.left = left;
            this.right = right;
            setName("thread-" + name);
        }

        @Override
        public void run() {
            while (true) {
                if (left.tryLock()) {
                    try {
                        if (right.tryLock()) {
                            try {
                                eating();
                            } finally {
                                right.unlock();
                            }
                        }
                    } finally {
                        left.unlock();
                    }
                }
            }
        }

        public void eating() {
            try {
                System.out.println(name + " eating");
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
